
## _to_ _pass_ _var_ _by_ _reference_ _use_: byref(var) === &var
import time 
from threading import Thread, Lock
from msvcrt import getch

from ctypes import cdll as dll, byref, c_char_p, c_void_p
#from ctypes import WinDLL as dll, byref, c_char_p, c_void_p
from ctypes import create_string_buffer, create_unicode_buffer
from ctypes import Structure, POINTER
from ctypes import c_int, c_uint8, c_uint16, c_uint32, c_uint64, c_double

## define structures used :
class CameraResult(Structure):
	_fields_ = [
		('interval', c_double),
		('status', c_int),
		]

class RawPixel(Structure):
	_fields_ = [
		('r', c_uint8),
		('g', c_uint8),
		('b', c_uint8),
		]

class HSV(Structure):
	_fields_ = [
		('h', c_uint8),
		('s', c_uint8),
		('v', c_uint8),
		]

class Filter(Structure):
	_fields_ = [
		('top', HSV),
		('bottom', HSV),
		]

class MouseEvent(Structure):
	_fields_ = [
		('triggered', c_int),
		('event', c_int),
		('x', c_int),
		('y', c_int),
		('flags', c_int),
		('pixel', RawPixel),
		('converted', HSV),
		]

camera_calibration = dll.camera_calibration
#camera_calibration = dll('camera_calibration')
print camera_calibration
#import sys
#sys.exit()

class CameraDevice:
	def __init__(self, camera_index):
		self._device = None
		## setup foreign functions ..
		self._initialize = camera_calibration.initialize
		self._initialize.restype = c_void_p
		self._UNinitialize = camera_calibration.UNinitialize
		self._run_camera = camera_calibration.run_camera
		self._run_camera.restype = CameraResult
		self._add_filter_to_camera = camera_calibration.add_filter_to_camera
		self._clear_filters = camera_calibration.clear_filters
		self._get_mouse_event = camera_calibration.get_mouse_event
		self._get_mouse_event.restype = MouseEvent
		
		## call initialize :
		address = self._initialize(0)
		if not address: raise Exception('CAMERA missing ..')
		self._device = c_void_p(address)
		print 'device %r - %r' % (self._device, type(self._device),)
	
	def clear_filters(self):
		if self._device:
			ret = self._clear_filters(self._device)
			return ret 
	def add_filter_to_camera(self, id_rawpixel, filter):
		if self._device:
			ret = self._add_filter_to_camera(self._device, id_rawpixel, filter)
			return ret 
	
	def __del__(self):
		if self._device != None:
			self._UNinitialize(self._device)
			self._device = None
	
	def run(self):
		if self._device != None:
			res = self._run_camera(self._device)
			#print res.status, res.interval
			return res
	
	def cleanup(self):
		if self._device != None:
			self._UNinitialize(self._device)
			self._device = None
	
	def _parse_file_parameters(self, filename):
		""" file format : r ,g ,b, e | high, low
		"""
		f = open( filename, 'rb' )
		data = f.read()
		data = data.replace(' ', '')
		data = data.replace('\n', '')
		data = data.replace('\r', '')
		q = data.split(',')
		ret = []
		for x in range(4):
			ret.append( Filter( (int(q[0]), int(q[1]), int(q[2]),), (int(q[3]), int(q[4]), int(q[5]),) ) )
			q = q[6:]
		return ret 


class KeyInfo:
	def __init__(self, **kw):
		self.key = ''
		self.processed = False
		self.__dict__.update(kw)

class Testing:
	ANGLE_INCREMENT = 5
	START_POSITION = 'store-start'
	
	def __init__(self, camera, filename):
		self.resource = Lock()
		
		self._commands = []
		self._keyboard = Thread(target=self.keyboard_thread)
		self._keyboard.setDaemon(True)
		self._keyboard.start()
		self._key_resource = Lock()
		self.camera = camera 
		
		filters = self.camera._parse_file_parameters(filename)
		if len(filters) != 4:
			raise Exception('config format error ..')
		self.constants = dict( zip( ['red', 'green', 'blue', 'empty',], filters ) )
		self.markings = {
			'red' : RawPixel(250,0,0),
			'green' : RawPixel(0,250,0),
			'blue' : RawPixel(0,0,250),
			'empty' : RawPixel(250,250,250),
			}
		self.current_object = 0 
		self.current_object_name = 'red'
		
		self.increment = 1
		
		self.recreate_filters()
	
	def keyboard_thread(self):
		while 1:
			ch = getch()
			self._key_resource.acquire()
			self._commands.append( KeyInfo(key=ch) )
			self._key_resource.release()
			time.sleep(0.001)
	
	def input_thread(self):
		while 1:
			self._key_resource.acquire()
			commands = self._commands
			self._commands = []
			self._key_resource.release()
			
			for command in commands:
				# process key
				key = command.key
				filter = self.constants[self.current_object_name]
				
				if key == '1': filter.top += self.increment
				if key == 'q': filter.top -= self.increment
				if key == '2': filter.top += self.increment
				if key == 'w': filter.top -= self.increment
				if key == '3': filter.top += self.increment
				if key == 'e': filter.top -= self.increment
				
				if key == 'a': filter.bottom += self.increment
				if key == 'z': filter.bottom -= self.increment
				if key == 's': filter.bottom += self.increment
				if key == 'x': filter.bottom -= self.increment
				if key == 'd': filter.bottom += self.increment
				if key == 'c': filter.bottom -= self.increment
				
				if key == 'm':	## change step scale
					if self.increment == 1: self.increment = 10
					else: self.increment = 1
				if key == 'n':
					self.current_object += 1
					objects = self.constants.keys()
					if len(objects) > self.current_object:
						self.current_object = 0 
					self.current_object_name = objects[self.current_object] 
					print 'changed to:', objects[self.current_object]
					filter = self.constants[self.current_object_name]
				
				elif key == '\x1b':
					import sys
					sys.exit()
				else : 
					print 'key: %r' % (key, )
				
				print 'top[h:%s s:%s v:%s] bottom[h:%s s:%s v:%s]' % (filter.top.h, filter.top.s, filter.top.v, filter.bottom.h, filter.bottom.s, filter.bottom.v, )
				self.recreate_filters()
				
				#break
			time.sleep(0.05)

	def recreate_filters(self):
		self.resource.acquire()
		self.camera.clear_filters()
		for name, filter, in self.constants.items():
			id = self.markings[name]
			self.camera.add_filter_to_camera(id, filter)
		self.resource.release()
	
	def run(self):
		t = Thread(target=self.input_thread)
		t.setDaemon(True)
		t.start()
		
		while 1:
			self.resource.acquire()
			self.camera.run()
			self.resource.release()


if __name__ == '__main__':

	camera = CameraDevice(0)
	test = Testing(camera, 'boje.txt')
	
	dev_iterator = range(3)
	
	while 1:
		for x in dev_iterator:
			camera.run()
		event = camera._get_mouse_event(camera._device)
		if event.triggered:
			print 'event: %s (%s, %s)' % (event.event, event.x, event.y,)

	camera.cleanup()
	import sys 
	sys.exit()












